package com.chenfan.mcn.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chenfan.common.config.Constant;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.utils.DingTalkAlarm;
import com.chenfan.mcn.clients.baseinfo.BaseCustomer;
import com.chenfan.mcn.clients.baseinfo.BaseCustomerBillingVO;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.finance.FinanceClient;
import com.chenfan.mcn.clients.finance.FinanceEntityUpdateDto;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.clients.privilege.ScompanyRes;
import com.chenfan.mcn.component.DingTalkAlarmSender;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.*;
import com.chenfan.mcn.dao.*;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.common.extension.lock.DistributedLockTemplate;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.ApprovalFlowDTO;
import com.chenfan.mcn.model.dto.ChangeApprovalDTO;
import com.chenfan.mcn.model.dto.IncomeAgreementAddDTO;
import com.chenfan.mcn.model.vo.BasicExcutionOrderVO;
import com.chenfan.mcn.model.vo.ContractAgreementVO;
import com.chenfan.mcn.model.vo.IncomeContractAgreementVO;
import com.chenfan.mcn.mq.producer.IncomeContractAgreementMessageProducer;
import com.chenfan.mcn.service.*;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.process.vo.ApprovalOperationVO;
import com.chenfan.process.vo.NextNotifyVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @author tangwei
 * Date:     2021/1/26 10:14
 * Description: 收入合同补充协议
 */
@Slf4j
@Service
@SuppressWarnings({"deprecation", "AlibabaUndefineMagicConstant", "AlibabaRemoveCommentedCode", "AlibabaMethodTooLong"})
public class IncomeContactAgreementServiceImpl implements IncomeContactAgreementService, ApprovalCallbackService {

    @Autowired
    private IncomeContactAgreementMapper incomeContactAgreementMapper;

    @Autowired
    private ContractExcutionOrderService contractExcutionOrderService;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private IncomeContractService incomeContractService;

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private ContractExcutionOrderMapper contractExcutionOrderMapper;

    @Autowired
    private IncomeContractAgreementMessageProducer incomeContractAgreementMessageProducer;

    @Autowired
    private FinanceClient financeClient;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private StarPlatformInfoService starPlatformInfoService;

    @Autowired
    private DocIntentionOrderMapper docIntentionOrderMapper;

    private static final String APPROVAL_KEY = "approval::contract::";

    @Autowired
    private DingTalkAlarmSender dingTalkAlarmSender;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAgreement(IncomeAgreementAddDTO agreementAddDTO) {
        IncomeContract incomeContract = incomeContractMapper.selectById(agreementAddDTO.getIncomeContractId());
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isFalse(AgreementChangeContentEnum.containsInvalid(agreementAddDTO.getChangeContent()), "仅允许修改「我司合同主体、形式合同平台订单号」！");
        List<ContractExcutionOrder> contractExcutionOrders = CommonUtil.defaultList(contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId())
                .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode())
                .eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO)));
        //如果更改开票抬头，则校验
        /*if (AgreementChangeContentEnum.containsInvoiceInfo(agreementAddDTO.getChangeContent())) {
            IncomeContractAgreementChecker.verifyInvoice(agreementAddDTO);
            // 校验原收入合同对用费用表是否有未作废的费用
            Integer invalidCount = financeClient.getInvalid(incomeContract.getContractCode(), null, FinanceChargeTypeEnum.LIVE_CONTRACT_CHARGE.getType()).getObj();
            BusinessAssert.isTrue(invalidCount <= 0, McnErrorCode.PLEASE_INVALID_INCOME_CONTRACT_CHARGE);
            BusinessAssert.isTrue(IncomeContractTypeEnum.allowChangeInvoice(incomeContract.getContractType()), McnErrorCode.NO_ALLOW_CHANGE_INVOICE_INFO);
        } else {
            agreementAddDTO.clearInvoice();
        }*/
        IncomeContractAgreement incomeContractAgreement = new IncomeContractAgreement();
        if (AgreementChangeContentEnum.containsCompanyContractSubject(agreementAddDTO.getChangeContent())) {
            BusinessAssert.notNull(agreementAddDTO.getCompanyContractSubjectIdAfter(), McnErrorCode.PARAM_ERROR, "变更后-我司合同主体不能为空");
            BusinessAssert.isFalse(agreementAddDTO.getCompanyContractSubjectIdAfter().equals(incomeContract.getContractingId()),
                    McnErrorCode.PARAM_ERROR, "我司合同主体-变更前后须不一样" );
            incomeContractAgreement.setCompanyContractSubjectIdBefore(incomeContract.getContractingId());
            incomeContractAgreement.setCompanyContractSubjectIdAfter(agreementAddDTO.getCompanyContractSubjectIdAfter());
        }
        if (AgreementChangeContentEnum.containsPlatformOrderCode(agreementAddDTO.getChangeContent())) {
            BusinessAssert.isTrue(IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType()), "非形式合同不可变更平台订单号");
            BusinessAssert.isTrue(CommonUtil.defaultList(contractExcutionOrders).size() == 1, "多条执行单不允许修改平台订单号!");
            BusinessAssert.notNull(agreementAddDTO.getPlatformOrderCodeAfter(), McnErrorCode.PARAM_ERROR, "变更后-平台订单号不能为空");
            for (ContractExcutionOrder contractExcutionOrder : contractExcutionOrders) {
                BusinessAssert.isFalse(agreementAddDTO.getPlatformOrderCodeAfter().equals(contractExcutionOrder.getPlatformOrderCode()),
                        McnErrorCode.PARAM_ERROR, "平台订单号-变更前后须不一样" );
                incomeContractAgreement.setPlatformOrderCodeBefore(contractExcutionOrder.getPlatformOrderCode());
                incomeContractAgreement.setPlatformOrderCodeAfter(agreementAddDTO.getPlatformOrderCodeAfter());
                contractExcutionOrder.setPlatformOrderCode(agreementAddDTO.getPlatformOrderCodeAfter());
            }
            List<ContractExcutionOrder> platformReportIsFalseList = contractExcutionOrders.stream().filter(x ->
                    !ExcutionApprovalStatusEnum.isInvalid(x.getApprovalStatus()) && Boolean.FALSE.equals(x.getPlatformReport())).collect(Collectors.toList());
            BusinessAssert.isTrue(CollectionUtils.isEmpty(platformReportIsFalseList), ParamErrorCst.FORM_CONTRACT_PLATFORM_REPORT_IS_TRUE);
            contractExcutionOrderService.verifyPlatformOrderNumber(incomeContract.getId(), contractExcutionOrders);
        }
        if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            agreementAddDTO.setOriginalAmount(null);
        }
        //校验关联意向单
//        if(CollectionUtils.isNotEmpty(agreementAddDTO.getContractExcutionOrders())) {
//            List<Long> intentionOrderIds = agreementAddDTO.getContractExcutionOrders().stream().map(ContractExcutionOrder::getIntentionOrderId).filter(Objects::nonNull).collect(Collectors.toList());
//            if(CollectionUtils.isNotEmpty(intentionOrderIds)) {
//                BusinessAssert.isTrue(docIntentionOrderMapper.notExist(Wrappers.lambdaQuery(DocIntentionOrder.class)
//                        .in(DocIntentionOrder::getId, intentionOrderIds)
//                        .notIn(DocIntentionOrder::getStatus, Arrays.asList(IntentionOrderStatusEnum.CONRIMED.getCode(),IntentionOrderStatusEnum.EXECUTING.getCode(), IntentionOrderStatusEnum.EXECUTED.getCode()))
//                        .eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO)), McnErrorCode.INCOME_ADD_INTENTION_ORDER_ERROR);
//            }
//        }
        //如果该收入合同类型-带执行单，则校验变更合同金额
        //checkTheContractAmountOfChange(agreementAddDTO, incomeContract);
        boolean result;
        BeanUtils.copyProperties(agreementAddDTO, incomeContractAgreement);
        if (agreementAddDTO.getId() == null) {
            incomeContractAgreement.setAgreementCode(CodeGenerateHelper.getCode(BillCodeCst.INCOME_CONTRACT_AGREEMENT));
            result = incomeContactAgreementMapper.insert(incomeContractAgreement) > 0;
        } else {
            saveVertifyStatus(agreementAddDTO.getId());
            // 插入收入合同补充协议操作日志
            IncomeContractAgreement agreement = incomeContactAgreementMapper.selectById(agreementAddDTO.getId());
            BusinessAssert.notNull(agreement, McnErrorCode.AGREEMENT_NOT_EXISTS);
            result = incomeContactAgreementMapper.update(incomeContractAgreement,
                    Wrappers.lambdaUpdate(IncomeContractAgreement.class).eq(IncomeContractAgreement::getId, agreementAddDTO.getId())
                            .set(Objects.isNull(incomeContractAgreement.getInvoiceForm()), IncomeContractAgreement::getInvoiceForm, incomeContractAgreement.getInvoiceForm())
                            .set(Objects.isNull(incomeContractAgreement.getCustomerBillingId()), IncomeContractAgreement::getCustomerBillingId, incomeContractAgreement.getCustomerBillingId())
                            .set(Objects.isNull(incomeContractAgreement.getInvoiceType()), IncomeContractAgreement::getInvoiceType, incomeContractAgreement.getInvoiceType())
                            .set(Objects.isNull(incomeContractAgreement.getInvoiceContent()), IncomeContractAgreement::getInvoiceContent, incomeContractAgreement.getInvoiceContent())
                            .set(Objects.isNull(incomeContractAgreement.getInvoiceRemark()), IncomeContractAgreement::getInvoiceRemark, incomeContractAgreement.getInvoiceRemark())) > 0;
            incomeContractAgreement = incomeContactAgreementMapper.selectById(agreement.getId());
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(agreement.getId())
                    .businessType(LogBusinessTypeEnum.INCOME_CONTRACT_AGREEMENT)
                    .compare(agreement, incomeContractAgreement)
                    .build());
        }
        if (result) {
//            List<ContractExcutionOrder> contractExcutionOrders = agreementAddDTO.getContractExcutionOrders();
//            if (CollectionUtils.isNotEmpty(contractExcutionOrders)) {
//                List<ContractExcutionOrder> incomeContractExcutionOrders = CommonUtil.defaultList(this.getListByIncomeContractId(incomeContractAgreement.getIncomeContractId(), incomeContractAgreement.getId()));
//                incomeContractExcutionOrders.addAll(contractExcutionOrders);
//                incomeContractService.remindDuplicateEntry(agreementAddDTO.getApprovalStatus(), incomeContractExcutionOrders);
//                this.fillInSystemAdmin(contractExcutionOrders);
//                contractExcutionOrders.forEach(contractExcutionOrder -> {
//                    contractExcutionOrder.setIncomeContractId(incomeContractAgreement.getIncomeContractId());
//                    contractExcutionOrder.setContractAgreementId(incomeContractAgreement.getId());
//                });
//                contractExcutionOrderService.batchSave(contractExcutionOrders, incomeContractAgreement, incomeContract);
//                if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
//                    if (AgreementChangeContentEnum.containsExcOrder(agreementAddDTO.getChangeContent())) {
//                        BigDecimal nonVoidStatusTotalAmount = contractExcutionOrderMapper.totalAmountOfExecutionOrder(agreementAddDTO.getIncomeContractId());
//                        if (Objects.isNull(nonVoidStatusTotalAmount)) {
//                            nonVoidStatusTotalAmount = BigDecimal.ZERO;
//                        }
//                        BigDecimal advertisingTotal = ObjectUtils.defaultIfNull(incomeContract.getRoiAdvAmt(), BigDecimal.ZERO).add(ObjectUtils.defaultIfNull(incomeContract.getNoroiAdvAmt(), BigDecimal.ZERO));
//                        if (nonVoidStatusTotalAmount.compareTo(advertisingTotal) != 0) {
//                            throw new BusinessException(McnErrorCode.AMOUNT_OF_THE_EXECUTIO_NMUST_BE_EQUAL);
//                        }
//                    }
//                }
//            }
            //保存并提交=》启动审批流
            if (ApprovalStatusEnum.isApproval(agreementAddDTO.getApprovalStatus())) {
                BusinessAssert.isTrue(incomeContactAgreementMapper.notExist(Wrappers.lambdaQuery(IncomeContractAgreement.class)
                        .eq(IncomeContractAgreement::getIncomeContractId, incomeContract.getId())
                        .ne(IncomeContractAgreement::getId, incomeContractAgreement.getId())
                        .in(IncomeContractAgreement::getApprovalStatus, Arrays.asList(
                                ApprovalStatusEnum.UN_COMMIT.getCode(),
                                ApprovalStatusEnum.APPROVAL.getCode(),
                                ApprovalStatusEnum.REJECTED.getCode(),
                                ApprovalStatusEnum.CANCEL.getCode()))
                        .eq(IncomeContractAgreement::getIsDelete, NumberCst.ZERO)
                ), "当前合同已存在进行中的补充协议，请勿重复添加！");
                incomeContractService.updateExpectedAmount(incomeContract.getId());
                approvalFlowService.startProcess(incomeContractAgreement.getId(), incomeContractAgreement.getIncomeContractId(), incomeContractAgreement.getAgreementCode(), ApprovalEnum.getEnumByContractAgreementType(incomeContract.getContractType()), JSON.toJSONString(incomeContractAgreement),null);
                if (InvoiceFormEnum.needAutoInvoice(incomeContract.getInvoiceForm()) || InvoiceFormEnum.needAutoInvoice(agreementAddDTO.getInvoiceForm())) {
                    stringRedisTemplate.opsForValue().set(Constant.AUTHORIZATION + ":" + APPROVAL_KEY + incomeContractAgreement.getId(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
                }
            }
        }
        return result;
    }

    /**
     * 保存时校验状态
     * @param incomeContractId
     */
    private void saveVertifyStatus(Long incomeContractId) {
        IncomeContractAgreement incomeContract = incomeContactAgreementMapper.selectById(incomeContractId);
        if (incomeContract.getApprovalStatus() != ApprovalStatusEnum.UN_COMMIT.code() &&
                incomeContract.getApprovalStatus() != ApprovalStatusEnum.REJECTED.code() &&
                incomeContract.getApprovalStatus() != ApprovalStatusEnum.CANCEL.code()) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_UPDATE_ERROR);
        }
    }

    /**
     * 保存并提交=》启动审批流
     *
     * @param agreementAddDTO {@link IncomeAgreementAddDTO}
     * @param incomeContract  {@link IncomeContract}
     * @param supplier        {@link Supplier<IncomeContractAgreement>}
     */
    @Deprecated
    private void startProcess(IncomeAgreementAddDTO agreementAddDTO, IncomeContract incomeContract, Supplier<IncomeContractAgreement> supplier) {
        /*if (AgreementChangeContentEnum.containsCompanyContractSubject(agreementAddDTO.getChangeContent())) {
            FinanceVerifyResultVo resultVo = financeClient.existTaxInvoiceOrClear(incomeContract.getContractCode()).getObj();
            if(ObjectUtils.defaultIfNull(resultVo.getExistTaxInvoice(), Boolean.FALSE).booleanValue() || ObjectUtils.defaultIfNull(resultVo.getExistClear(), Boolean.FALSE).booleanValue()) {
                throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(), "收入合同已存在开票记录或者核销记录，无法修改我司合同主体！");
            }
        }*/
        IncomeContractAgreement incomeContractAgreement = supplier.get();
        /*if (this.isAdAmountChange(incomeContract, incomeContractAgreement)) {
            Integer invalidCount = financeClient.getInvalid(incomeContract.getContractCode(), null, FinanceChargeTypeEnum.LIVE_CONTRACT_CHARGE.getType()).getObj();
            //校验原收入合同对用费用表是否有未作废的费用
            BusinessAssert.isTrue(invalidCount <= 0, McnErrorCode.PLEASE_INVALID_LIVE_CONTRACT_CHARGE);
        }*/
        verifyAgreementIncludingExecutionOrder(agreementAddDTO, incomeContract);
        incomeContractService.updateExpectedAmount(incomeContract.getId());
        approvalFlowService.startProcess(incomeContractAgreement.getId(), incomeContractAgreement.getIncomeContractId(), incomeContractAgreement.getAgreementCode(), ApprovalEnum.getEnumByContractAgreementType(incomeContract.getContractType()), JSON.toJSONString(incomeContractAgreement),null);
        if (InvoiceFormEnum.needAutoInvoice(incomeContract.getInvoiceForm()) || InvoiceFormEnum.needAutoInvoice(agreementAddDTO.getInvoiceForm())) {
            stringRedisTemplate.opsForValue().set(Constant.AUTHORIZATION + ":" + APPROVAL_KEY + incomeContractAgreement.getId(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
        }
    }

    @Deprecated
    private void verifyAgreementIncludingExecutionOrder(IncomeAgreementAddDTO agreementAddDTO, IncomeContract incomeContract) {
        //boolean result = IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) && AgreementChangeContentEnum.containsExcOrder(agreementAddDTO.getChangeContent());
        List<ContractExcutionOrder> executionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .eq(ContractExcutionOrder::getIsDelete, Boolean.FALSE)
                .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId())
                .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode()));
//        if (result) {
//            BigDecimal reduce = new BigDecimal(String.valueOf(BigDecimal.ZERO));
//            if (CollectionUtils.isNotEmpty(executionOrderList)) {
//                reduce = executionOrderList.stream().map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//            }
//            BigDecimal adAmount = AgreementChangeContentEnum.containsAmount(agreementAddDTO.getChangeContent()) ? agreementAddDTO.getAdAmount() : incomeContract.getAdAmount();
//            if(Objects.equals(incomeContract.getContainsAdvertising(),1)) {
//                BusinessAssert.isTrue(reduce.compareTo(adAmount) == 0, McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
//            }
//        }
        if (IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType())) {
            List<ContractExcutionOrder> platformReportIsFalseList = executionOrderList.stream().filter(x ->!Integer.valueOf(9).equals(x.getApprovalStatus()) && Boolean.FALSE.equals(x.getPlatformReport())).collect(Collectors.toList());
            BusinessAssert.isTrue(CollectionUtils.isEmpty(platformReportIsFalseList), ParamErrorCst.FORM_CONTRACT_PLATFORM_REPORT_IS_TRUE);
        }
    }


    /**
     * 校验变更合同金额
     *
     * @param agreementAddDTO {@link IncomeAgreementAddDTO}
     */
    @Deprecated
    private void checkTheContractAmountOfChange(IncomeAgreementAddDTO agreementAddDTO, IncomeContract incomeContract) {
        deleteExcutionOrdersWithAgreement(agreementAddDTO.getId(), agreementAddDTO.getContractExcutionOrders());
        if (!IncomeContractTypeEnum.isFrameContract(incomeContract.getContractType())) {
            boolean includeContractAmount = AgreementChangeContentEnum.containsAmount(agreementAddDTO.getChangeContent());
            boolean includeExecutionOrder = AgreementChangeContentEnum.containsExcOrder(agreementAddDTO.getChangeContent());
            //只有在审批中是才会校验金额
            if (ApprovalStatusEnum.isApproval(agreementAddDTO.getApprovalStatus())) {
                verifyContractAgreement(agreementAddDTO, incomeContract, includeContractAmount, includeExecutionOrder);
            }
        }
    }

    /**
     * 非框架合同&非直播合同补充协议校验
     *
     * @param agreementAddDTO       {@link IncomeAgreementAddDTO}
     * @param incomeContract        {@link IncomeContract}
     * @param includeContractAmount {@link Boolean}
     * @param includeExecutionOrder {@link Boolean}
     */
    public void verifyContractAgreement(IncomeAgreementAddDTO agreementAddDTO, IncomeContract incomeContract, boolean includeContractAmount, boolean includeExecutionOrder) {
        BigDecimal nonVoidStatusTotalAmount = contractExcutionOrderMapper.totalAmountOfExecutionOrder(agreementAddDTO.getIncomeContractId());
        if (Objects.isNull(nonVoidStatusTotalAmount)) {
            nonVoidStatusTotalAmount = BigDecimal.ZERO;
        }

        if (!includeContractAmount && includeExecutionOrder) {
            BigDecimal totalAmount = totalAmount(agreementAddDTO, nonVoidStatusTotalAmount);
            if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
//                if(Objects.equals(incomeContract.getContainsAdvertising(), NumberCst.ONE)) {
//                    if (totalAmount.compareTo(incomeContract.getAdAmount()) != 0) {
//                        throw new BusinessException(McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
//                    }
//                }
            } else {
                if (totalAmount.compareTo(incomeContract.getBusinessAmount()) != 0) {
                    throw new BusinessException(McnErrorCode.AMOUNT_MUST_BE_EQUAL);
                }
            }
        } else if (includeContractAmount && !includeExecutionOrder) {
            if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
                // verifyLiveContractAgreement(agreementAddDTO);
                if (nonVoidStatusTotalAmount.compareTo(agreementAddDTO.getAdAmount()) != 0) {
                    throw new BusinessException(McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
                }
            } else {
                if (nonVoidStatusTotalAmount.compareTo(agreementAddDTO.getCurrentAmount()) != 0) {
                    throw new BusinessException(McnErrorCode.AMOUNT_MUST_BE_EQUAL);
                }
            }
        } else if (includeContractAmount && includeExecutionOrder) {
            BigDecimal totalAmount = totalAmount(agreementAddDTO, nonVoidStatusTotalAmount);
            if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
                // verifyLiveContractAgreement(agreementAddDTO);
                if (totalAmount.compareTo(agreementAddDTO.getAdAmount()) != 0) {
                    throw new BusinessException(McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
                }
            } else {
                if (totalAmount.compareTo(agreementAddDTO.getCurrentAmount()) != 0) {
                    throw new BusinessException(McnErrorCode.AMOUNT_MUST_BE_EQUAL);
                }
            }
        }
    }


    /**
     * 获取执行单总金额
     *
     * @param agreementAddDTO          {@link IncomeAgreementAddDTO}
     * @param nonVoidStatusTotalAmount {@link BigDecimal}
     * @return {@link BigDecimal}
     */
    public BigDecimal totalAmount(IncomeAgreementAddDTO agreementAddDTO, BigDecimal nonVoidStatusTotalAmount) {
        if (Objects.nonNull(agreementAddDTO.getId())) {
            List<ContractExcutionOrder> agreementExecutionOrders = agreementAddDTO.getContractExcutionOrders();
            //查询收入合同关联执行单
            List<ContractExcutionOrder> contractExecutionOrders = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                    .eq(ContractExcutionOrder::getIncomeContractId, agreementAddDTO.getIncomeContractId())
                    .eq(ContractExcutionOrder::getIsDelete, Boolean.FALSE)
                    .notIn(ContractExcutionOrder::getApprovalStatus, ApprovalStatusEnum.INVALID.code()));
            if (CollectionUtils.isNotEmpty(agreementExecutionOrders) && CollectionUtils.isNotEmpty(contractExecutionOrders)) {
                List<Long> executionOrderIds = agreementExecutionOrders.stream().map(ContractExcutionOrder::getId).collect(Collectors.toList());
                List<ContractExcutionOrder> executionOrderList = contractExecutionOrders.stream().filter(a -> !executionOrderIds.contains(a.getId())).collect(Collectors.toList());
                nonVoidStatusTotalAmount = executionOrderList.stream().map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            } else {
                nonVoidStatusTotalAmount = null;
            }
        }
        BigDecimal newAddTotalAmount = agreementAddDTO.getContractExcutionOrders().stream()
                .filter(c -> !ApprovalStatusEnum.isInvalid(c.getApprovalStatus()))
                .map(ContractExcutionOrder::getActualQuotedPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalAmount;
        if (Objects.nonNull(nonVoidStatusTotalAmount)) {
            totalAmount = nonVoidStatusTotalAmount.add(newAddTotalAmount);
        } else {
            totalAmount = newAddTotalAmount;
        }
        return totalAmount;
    }

    /**
     * 直播合同补充协议包含变更合同金额，保存时需要校验，变更后直播金额+广告金额等于【商务确认合同金额】
     *
     * @param agreementAddDTO {@link IncomeAgreementAddDTO}
     */
    // public void verifyLiveContractAgreement(IncomeAgreementAddDTO agreementAddDTO) {
    //     BigDecimal sum = agreementAddDTO.getLiveAmount().add(agreementAddDTO.getAdAmount());
    //     if (sum.compareTo(agreementAddDTO.getCurrentAmount()) != 0) {
    //         throw new BusinessException(McnErrorCode.AGREEMENT_AMOUNT_MUST_BE_EQUAL);
    //     }
    // }


    /**
     * 删除补充协议录入的执行单
     *
     * @param agreementId             {@link Long}
     * @param contractExecutionOrders {@link List<ContractExcutionOrder>}
     */
    @Deprecated
    public void deleteExcutionOrdersWithAgreement(Long agreementId, List<ContractExcutionOrder> contractExecutionOrders) {
        if (Objects.nonNull(agreementId) && CollectionUtils.isNotEmpty(contractExecutionOrders)) {
            List<ContractExcutionOrder> executionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                    .eq(ContractExcutionOrder::getContractAgreementId, agreementId)
                    .eq(ContractExcutionOrder::getIsDelete, Boolean.FALSE));
            List<Long> executionIds = contractExecutionOrders.stream().map(ContractExcutionOrder::getId).collect(Collectors.toList());
            List<ContractExcutionOrder> delExecutions = executionOrderList.stream().filter(x -> !executionIds.contains(x.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(delExecutions)) {
                for (ContractExcutionOrder contractExcutionOrder : delExecutions) {
                    ContractExcutionOrder deleteEntity = new ContractExcutionOrder();
                    deleteEntity.setId(contractExcutionOrder.getId());
                    deleteEntity.setIsDelete(1);
                    contractExcutionOrderMapper.updateById(deleteEntity);
                }
                //补充协议删除的执行单-解绑意向单
                List<Long> idList = delExecutions.stream().map(ContractExcutionOrder::getId).filter(Objects::nonNull).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(idList)) {
                    docIntentionOrderMapper.updateByNoStrategy(Wrappers.<DocIntentionOrder>lambdaUpdate()
                            .set(DocIntentionOrder::getExcutionOrderId, null)
                            .set(DocIntentionOrder::getExcutionOrderCode, null)
                            .set(DocIntentionOrder::getIncomeContractId, null)
                            .set(DocIntentionOrder::getIncomeContractCode, null)
                            .set(DocIntentionOrder::getUpdateBy, UserVoContextHolder.getUserId())
                            .set(DocIntentionOrder::getUpdateName, UserVoContextHolder.getUserName())
                            .set(DocIntentionOrder::getUpdateDate, new Date())
                            .in(DocIntentionOrder::getExcutionOrderId, idList));
                }
            }
        }
    }

    @Override
    public List<ContractAgreementVO> agreementList(Long incomeContractId, Integer contractType) {
        List<IncomeContractAgreementVO> incomeContractAgreements = incomeContactAgreementMapper.info(incomeContractId,
                ApprovalEnum.getContractAgreementProcessIds());
        if (CollectionUtils.isEmpty(incomeContractAgreements)) {
            return new ArrayList<>(0);
        }
        List<ScompanyRes> companyResList = privilegeClient.getParList().getObj();
        Map<Long, String> companyMap = companyResList.stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
        List<ContractAgreementVO> contractAgreementVOList = incomeContractAgreements.stream().map(e -> {
            ContractAgreementVO contractAgreementVO = new ContractAgreementVO();
            BeanUtils.copyProperties(e, contractAgreementVO);
            if (Objects.nonNull(e.getCustomerBillingId())) {
                BaseCustomerBillingVO baseCustomerBillingVO = baseInfoClient.getBillingsInfoById(e.getCustomerBillingId()).getObj();
                contractAgreementVO.setCustomerSignSubject(Objects.nonNull(baseCustomerBillingVO) ? baseCustomerBillingVO.getInvoiceTitle() : null);
            }
            if (AgreementChangeContentEnum.containsCompanyContractSubject(contractAgreementVO.getChangeContent())) {
                contractAgreementVO.setBeforeCompanyContractSubject(companyMap.get(contractAgreementVO.getCompanyContractSubjectIdBefore()));
                contractAgreementVO.setAfterCompanyContractSubject(companyMap.get(contractAgreementVO.getCompanyContractSubjectIdAfter()));
            }
            return contractAgreementVO;
        }).collect(Collectors.toList());

        List<Long> agreementIds = contractAgreementVOList.stream().map(ContractAgreementVO::getId).collect(Collectors.toList());
        List<ContractExcutionOrder> excutionOrders = contractExcutionOrderService.getByAgreement(agreementIds);
        if (CollectionUtils.isNotEmpty(excutionOrders)) {
            // 组装执行单信息并按收入合同协议id分组
            List<BasicExcutionOrderVO> basicExcutionOrderVOList = contractExcutionOrderService.basicExcutionOrderList(excutionOrders);
            //查询执行单客户信息
            Set<Long> customerIdList = basicExcutionOrderVOList.stream().map(x -> x.getCustomerId()).filter(y -> Objects.nonNull(y)).collect(Collectors.toSet());
            Map<Long, BaseCustomer> baseCustomerMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () ->
                            Optional.ofNullable(baseInfoClient.getMcnCustomerByIds(new ArrayList<>(customerIdList))).map(x -> x.getObj()).orElse(Collections.EMPTY_MAP)
                    , Collections.EMPTY_MAP);
            //查询意向单
            List<Long> excuteOrderIds = basicExcutionOrderVOList.stream().map(x -> x.getId()).collect(Collectors.toList());
            Map<Long, DocIntentionOrder> intentionOrderMap = CommonUtil.getIfNecessary(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(excuteOrderIds), () ->
                            CommonUtil.defaultList(docIntentionOrderMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrder.class).in(DocIntentionOrder::getExcutionOrderId, excuteOrderIds)))
                                    .stream().collect(Collectors.toMap(DocIntentionOrder::getExcutionOrderId, x -> x, (x, y) -> x))
                    , Collections.EMPTY_MAP);
            Map<Long, List<BasicExcutionOrderVO>> excutionOrderMap = basicExcutionOrderVOList.stream().map(e->{
                BaseCustomer customer = baseCustomerMap.get(e.getCustomerId());
                if (Objects.nonNull(customer)) {
                    e.setCustomerId(customer.getCustomerId());
                    e.setCustomerName(customer.getCustomerNameC());
                    e.setCustomerCode(customer.getCustomerCode());
                }
                DocIntentionOrder intentionOrder = intentionOrderMap.get(e.getId());
                if(Objects.nonNull(intentionOrder)) {
                    e.setIntentionOrderId(intentionOrder.getId());
                    e.setIntentionCode(intentionOrder.getIntentionCode());
                    e.setIsLiveAd(intentionOrder.getIsLiveAd());
                    e.setHaveDiscountApproval(intentionOrder.getHaveDiscountApproval());
                    e.setDiscountScreenshot(intentionOrder.getDiscountScreenshot());
                }
                e.setPlatformOrderNumber(e.getPlatformOrderCode());
                e.setBrandNameN(e.getBrandNameN());
                return e;
            }).collect(Collectors.groupingBy(BasicExcutionOrderVO::getContractAgreementId));
            for (ContractAgreementVO contractAgreementVO : contractAgreementVOList) {
                Long agreementId = contractAgreementVO.getId();
                contractAgreementVO.setExcutionOrders(excutionOrderMap.get(agreementId));
            }
        }

        List<Long> flowList = contractAgreementVOList.stream().map(ContractAgreementVO::getFlowId).distinct().collect(Collectors.toList());
        JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
        if (Objects.nonNull(flowMapping)) {
            if (flowMapping.size() > 0) {
                contractAgreementVOList.forEach(
                        agreementVO -> {
                            if (agreementVO.getFlowId() != null) {
                                agreementVO.setFlowStatusName(flowMapping.getString(agreementVO.getFlowId().toString()));
                            }
                        });
            }
        }
        return contractAgreementVOList;
    }

    @SuppressWarnings("AlibabaAvoidComplexCondition")
    private void validateStatus(IncomeContractAgreement incomeContract, Integer status) {
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.UN_COMMIT.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_COMMIT_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.APPROVAL.getCode() &&
                (status != ApprovalStatusEnum.CANCEL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_CANCEL_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.PASSED.getCode() &&
                (status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_PASSED_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.REJECTED.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_REJECTED_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.CANCEL.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_CANCEL_ERROR);
        }

    }

    /**
     * 修改单据状态
     *
     * @param agreementId    {@link Long}
     * @param approvalStatus {@link Integer}
     * @return {@link boolean}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changeStatus(Long agreementId, Integer approvalStatus) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT_AGREEMENT.generateKey(agreementId), () -> {
            IncomeContractAgreement agreement = incomeContactAgreementMapper.selectById(agreementId);
            BusinessAssert.notNull(agreement, McnErrorCode.AGREEMENT_NOT_EXISTS);

            validateStatus(agreement, approvalStatus);

            IncomeContract incomeContract = incomeContractMapper.selectById(agreement.getIncomeContractId());
            BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
            this.verifyApprovalStatus(agreement, approvalStatus, incomeContract, () ->
                    contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                            .eq(ContractExcutionOrder::getIsDelete, 0)
                            .eq(ContractExcutionOrder::getContractAgreementId, agreement.getId()))
            );
            IncomeContractAgreement updateAgreement = new IncomeContractAgreement();
            updateAgreement.setId(agreement.getId());
            updateAgreement.setApprovalStatus(approvalStatus);
            updateAgreement.setUpdateDate(new Date());
            boolean result = incomeContactAgreementMapper.updateById(updateAgreement) > 0;
            if (result) {
                ApprovalEnum approvalEnum = ApprovalEnum.getEnumByContractAgreementType(incomeContract.getContractType());
                boolean isChangeAmount = AgreementChangeContentEnum.containsAmount(agreement.getChangeContent());
                if (ApprovalStatusEnum.isApproval(approvalStatus)) {
                    /*if (AgreementChangeContentEnum.containsCompanyContractSubject(agreement.getChangeContent())) {
                        FinanceVerifyResultVo resultVo = financeClient.existTaxInvoiceOrClear(incomeContract.getContractCode()).getObj();
                        if(ObjectUtils.defaultIfNull(resultVo.getExistTaxInvoice(), Boolean.FALSE).booleanValue() || ObjectUtils.defaultIfNull(resultVo.getExistClear(), Boolean.FALSE).booleanValue()) {
                            throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(), "收入合同已存在开票记录或者核销记录，无法修改我司合同主体！");
                        }
                    }*/
//                    BusinessAssert.isTrue(docIntentionOrderMapper.notExist(Wrappers.lambdaQuery(DocIntentionOrder.class)
//                            .eq(DocIntentionOrder::getIncomeContractId, incomeContract.getId())
//                            .notIn(DocIntentionOrder::getStatus, Arrays.asList(IntentionOrderStatusEnum.CONRIMED.getCode(),IntentionOrderStatusEnum.EXECUTING.getCode(), IntentionOrderStatusEnum.EXECUTED.getCode()))
//                            .eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO)), McnErrorCode.INCOME_ADD_INTENTION_ORDER_ERROR);
                    List<ContractExcutionOrder> executionOrderList = this.getListByIncomeContractId(agreement.getIncomeContractId(), null);
                    //金额校验后置
                    if (!IncomeContractTypeEnum.isFrameContract(incomeContract.getContractType())) {
                        boolean includeContractAmount = AgreementChangeContentEnum.containsAmount(agreement.getChangeContent());
                        boolean includeExecutionOrder = AgreementChangeContentEnum.containsExcOrder(agreement.getChangeContent());
                        IncomeAgreementAddDTO agreementAddDTO = new IncomeAgreementAddDTO();
                        BeanUtils.copyProperties(agreement, agreementAddDTO);
                        agreementAddDTO.setContractExcutionOrders(executionOrderList);
                        verifyContractAgreement(agreementAddDTO, incomeContract, includeContractAmount, includeExecutionOrder);
                    }

                    if (IncomeContractTypeEnum.needVerifyExcutionAmount(incomeContract.getContractType())) {
                        BigDecimal businessAmount = isChangeAmount ? agreement.getCurrentAmount() : incomeContract.getBusinessAmount();
                        BusinessAssert.notEmpty(executionOrderList, McnErrorCode.NO_EXECUTION);
                        BigDecimal reduce = executionOrderList.stream().filter(o -> !ExcutionApprovalStatusEnum.INVALID.getCode().equals(o.getApprovalStatus())).map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BusinessAssert.isTrue(reduce.compareTo(businessAmount) == 0, McnErrorCode.EXCEEDING_CONTRACT_AMOUNT);
                    }
//                    if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) && AgreementChangeContentEnum.containsExcOrder(agreement.getChangeContent())) {
//                        BigDecimal adAmount = isChangeAmount ? agreement.getAdAmount() : incomeContract.getAdAmount();
//                        if (Objects.nonNull(adAmount)) {
//                            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(executionOrderList)) {
//                                BigDecimal reduce = executionOrderList.stream().filter(o -> !ExcutionApprovalStatusEnum.INVALID.getCode().equals(o.getApprovalStatus())).map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//                                BusinessAssert.isTrue(reduce.compareTo(adAmount) == 0, McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
//                            } else {
//                                BusinessAssert.isTrue(adAmount.compareTo(new BigDecimal(0)) == 0, McnErrorCode.MUST_BE_EQUAL_TO_AD_AMOUNT);
//                            }
//                        }
//                    }
                    incomeContractService.remindDuplicateEntry(approvalStatus, executionOrderList);
                    incomeContractService.updateExpectedAmount(incomeContract.getId());
                    approvalFlowService.startProcess(agreement.getId(), agreement.getIncomeContractId(), agreement.getAgreementCode(), approvalEnum, JSON.toJSONString(agreement), null);
                    if (InvoiceFormEnum.needAutoInvoice(incomeContract.getInvoiceForm()) || InvoiceFormEnum.needAutoInvoice(agreement.getInvoiceForm())) {
                        stringRedisTemplate.opsForValue().set(Constant.AUTHORIZATION + ":" + APPROVAL_KEY + agreement.getId(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
                    }
                }
                //如果收入合同补充协议撤回或作废，则撤回已提起的审批流程
                if (ApprovalStatusEnum.anyMatch(approvalStatus, ApprovalStatusEnum.CANCEL, ApprovalStatusEnum.INVALID)) {
                    approvalFlowService.revokeProcess(agreement.getId(), approvalEnum.getProcessId());
                }
                //操作日志
                EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                        .businessType(LogBusinessTypeEnum.INCOME_CONTRACT_AGREEMENT)
                        .compare(agreement, incomeContactAgreementMapper.selectById(agreementId))
                        .build());
            }
            return result;
        });
    }

    @Override
    public ApprovalOperationVO changeApproval(ChangeApprovalDTO dto, Long billId) {
        IncomeContractAgreement entity = incomeContactAgreementMapper.selectById(billId);
        BusinessAssert.notNull(entity, McnErrorCode.AGREEMENT_NOT_EXISTS);
        BusinessAssert.isFalse(ApprovalStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "已作废，不允许操作！");
        BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "非审批中，不允许操作！");
        return approvalFlowService.approvalChange(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), dto.getApprovalFlag(), dto.getRemark());
    }

    @Override
    public NextNotifyVo changeApprovalNext(ChangeApprovalDTO dto, Long billId) {
        IncomeContractAgreement entity = incomeContactAgreementMapper.selectById(billId);
        BusinessAssert.notNull(entity, McnErrorCode.AGREEMENT_NOT_EXISTS);
        BusinessAssert.isFalse(ApprovalStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "已作废，不允许操作！");
        BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "非审批中，不允许操作！");
        return approvalFlowService.approvalChangeNext(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), dto.getApprovalFlag(), dto.getRemark());
    }

    /**
     * 审批回调
     *
     * @param approvalFlowDTO 流程对对象
     * @param status          最后节点的同意 false 拒绝
     */
    @SuppressWarnings("AlibabaRemoveCommentedCode")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvalCallback(ApprovalFlowDTO approvalFlowDTO, Boolean status) {
        IncomeContractAgreement agreement = incomeContactAgreementMapper.selectById(approvalFlowDTO.getSrcId());
        BusinessAssert.notNull(agreement, McnErrorCode.AGREEMENT_NOT_EXISTS);
        approvalFlowDTO.setSrcCode(agreement.getIncomeContractCode());
        approvalFlowDTO.addSubmitInfoIfNull(agreement);
        Long incomeContractId = agreement.getIncomeContractId();
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractId);
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        LambdaUpdateWrapper<IncomeContract> lambdaUpdateWrapper = Wrappers.lambdaUpdate(IncomeContract.class).eq(IncomeContract::getId, incomeContractId);
        ApprovalEnum approvalEnum = ApprovalEnum.getEnumByContractAgreementType(incomeContract.getContractType());
        if (Objects.isNull(status)) {
            //审批流配置-接入待办
            return;
        }
        //流程审批结束
        Integer approvalStatus = status ? ApprovalStatusEnum.PASSED.code() : ApprovalStatusEnum.REJECTED.code();
        if (ApprovalStatusEnum.anyMatch(agreement.getApprovalStatus(), ApprovalStatusEnum.PASSED, ApprovalStatusEnum.REJECTED)) {
            log.error("收入合同补充协议-流程审批结束重复回调，不做处理！approvalId={}", approvalFlowDTO.getApprovalId());
            return;
        }

        BusinessAssert.isTrue(DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT_AGREEMENT.generateKey(agreement.getId()), () -> {
            IncomeContractAgreement updateAgreement = new IncomeContractAgreement();
            updateAgreement.setId(agreement.getId());
            updateAgreement.setApprovalStatus(approvalStatus);
            updateAgreement.setUpdateBy(approvalFlowDTO.getUserId());
            updateAgreement.setUpdateName(approvalFlowDTO.getUserName());
            updateAgreement.setUpdateDate(new Date());
            return incomeContactAgreementMapper.updateById(updateAgreement) > 0;
        }), McnErrorCode.FLOW_CALLBACK_HANDLE_EXCEPTION);

        // 补充协议(变更合同金额)审批通过更新收入合同的最新合同金额
        if (ApprovalStatusEnum.isPassed(approvalStatus)) {
            boolean includedAmount = AgreementChangeContentEnum.containsAmount(agreement.getChangeContent());
            boolean includedIncomeContract = AgreementChangeContentEnum.containsIncomeContact(agreement.getChangeContent());
            BusinessAssert.isTrue(DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContract.getId()), () -> {
                if (includedAmount) {
                    BigDecimal newBusinessAmount = agreement.getCurrentAmount();
//                    if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
//                        lambdaUpdateWrapper.set(IncomeContract::getAdAmount, agreement.getAdAmount());
//                        newBusinessAmount = ObjectUtils.defaultIfNull(incomeContract.getPitFeeAmount(), BigDecimal.ZERO)
//                                .add(ObjectUtils.defaultIfNull(incomeContract.getRoiServiceFee(), BigDecimal.ZERO))
//                                .add(ObjectUtils.defaultIfNull(agreement.getAdAmount(), BigDecimal.ZERO));
//                        if(ObjectUtils.defaultIfNull(agreement.getAdAmount(), BigDecimal.ZERO).compareTo(BigDecimal.ZERO) == 1) {
//                            lambdaUpdateWrapper.set(IncomeContract::getContainsAdvertising, NumberCst.ONE);
//                        }
//                    }
                    if (newBusinessAmount.compareTo(BigDecimal.ZERO) == 1 &&
                            BigDecimal.ZERO.compareTo(incomeContract.getPayBackAmount()) == 0) {
                        lambdaUpdateWrapper.set(IncomeContract::getPayBackStatus, NumberCst.ZERO);
                    } else if (newBusinessAmount.compareTo(incomeContract.getPayBackAmount()) == 1) {
                        lambdaUpdateWrapper.set(IncomeContract::getPayBackStatus, NumberCst.ONE);
                    } else {
                        lambdaUpdateWrapper.set(IncomeContract::getPayBackStatus, NumberCst.TWO);
                    }
                    lambdaUpdateWrapper.set(IncomeContract::getBusinessAmount, newBusinessAmount);
                }
                //如果合同标签是无合同的，则清空agreementAddDTO
                if (includedIncomeContract && McnConstant.NO_CONTRACT.equalsIgnoreCase(incomeContract.getContractTag())) {
                    lambdaUpdateWrapper.set(IncomeContract::getContractTag, null);
                }
                boolean includedPlatformOrderCode = AgreementChangeContentEnum.containsPlatformOrderCode(agreement.getChangeContent());
                if(includedPlatformOrderCode) {
                    List<ContractExcutionOrder> contractExcutionOrders = CommonUtil.defaultList(contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                            .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId())
                            .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode())
                            .eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO)));
                    if(CollectionUtils.isNotEmpty(contractExcutionOrders)) {
                        List<Long> excuteOrderIds = contractExcutionOrders.stream().map(x -> x.getId()).collect(Collectors.toList());
                        contractExcutionOrderMapper.updateByNoStrategy(Wrappers.lambdaUpdate(ContractExcutionOrder.class)
                                .in(ContractExcutionOrder::getId, excuteOrderIds)
                                .set(ContractExcutionOrder::getPlatformOrderCode, agreement.getPlatformOrderCodeAfter())
                                .set(ContractExcutionOrder::getUpdateBy, approvalFlowDTO.getUserId())
                                .set(ContractExcutionOrder::getUpdateName, approvalFlowDTO.getUserName())
                                .set(ContractExcutionOrder::getUpdateDate, new Date()));
                        contractExcutionOrders.forEach(e -> {
                            ContractExcutionOrder beforeItem = new ContractExcutionOrder();
                            beforeItem.setPlatformOrderCode(e.getPlatformOrderCode());
                            ContractExcutionOrder afterItem = new ContractExcutionOrder();
                            afterItem.setPlatformOrderCode(agreement.getPlatformOrderCodeAfter());
                            //操作日志
                            EventPublisher.post(OperateLogEvent.builder().businessId(e.getId())
                                    .businessType(LogBusinessTypeEnum.EXECUTION_ORDER)
                                    .compare(beforeItem, afterItem)
                                    .build(approvalFlowDTO.getUserId(), approvalFlowDTO.getUserName()));
                        });
                    }

                }
                boolean includedCompanyContractSubject = AgreementChangeContentEnum.containsCompanyContractSubject(agreement.getChangeContent());
                String companyContractSubject = null;
                if (includedCompanyContractSubject) {
                    lambdaUpdateWrapper.set(IncomeContract::getContractingId, agreement.getCompanyContractSubjectIdAfter());
                    List<ScompanyRes> companyResList = privilegeClient.getParList().getObj();
                    Map<Long, String> companyMap = companyResList.stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
                    companyContractSubject = companyMap.get(agreement.getCompanyContractSubjectIdAfter());
                    lambdaUpdateWrapper.set(IncomeContract::getCompanyContractSubject, companyContractSubject);
                }
                if(includedPlatformOrderCode || includedCompanyContractSubject) {
                    //按来源单号修改财务主体
                    FinanceEntityUpdateDto updateFinanceEntity = new FinanceEntityUpdateDto();
                    try {
                        updateFinanceEntity.setChargeSourceCode(incomeContract.getContractCode());
                        updateFinanceEntity.setFinanceEntity(companyContractSubject);
                        updateFinanceEntity.setChargeSourceDetail2(agreement.getPlatformOrderCodeAfter());
                        financeClient.updateFinanceEntity(updateFinanceEntity);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        DingTalkAlarm.send("更新财务主体及来源明细2异常告警", String.format("请求报文:%s， 异常信息：%s", JSONObject.toJSONString(updateFinanceEntity), e.getMessage()));
                    }
                }
                    /*if (includedInvoiceInfo) {
                        //开票信息
                        String customerSignSubject = null;
                        if (Objects.nonNull(agreement.getCustomerBillingId())) {
                            BaseCustomerBillingVO baseCustomerBillingVO = baseInfoClient.getBillingsInfoById(agreement.getCustomerBillingId()).getObj();
                            customerSignSubject = Objects.nonNull(baseCustomerBillingVO) ? baseCustomerBillingVO.getInvoiceTitle() : null;
                        }
                        lambdaUpdateWrapper.set(IncomeContract::getInvoiceForm, agreement.getInvoiceForm())
                                .set(IncomeContract::getInvoiceType, agreement.getInvoiceType())
                                .set(IncomeContract::getInvoiceContent, agreement.getInvoiceContent())
                                .set(IncomeContract::getInvoiceRemark, agreement.getInvoiceRemark())
                                .set(IncomeContract::getCustomerBillingId, agreement.getCustomerBillingId())
                                .set(IncomeContract::getCustomerSignSubject, agreement.getCustomerBillingId())
                                .set(StringUtils.isNotBlank(customerSignSubject), IncomeContract::getCustomerSignSubject, customerSignSubject);
                    }*/
                lambdaUpdateWrapper.set(IncomeContract::getUpdateBy, approvalFlowDTO.getUserId());
                lambdaUpdateWrapper.set(IncomeContract::getUpdateName, approvalFlowDTO.getUserName());
                lambdaUpdateWrapper.set(IncomeContract::getUpdateDate, new Date());
                boolean result = incomeContractMapper.updateByNoStrategy(lambdaUpdateWrapper);
                if (result) {
                    //操作日志
                    EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                            .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                            .compare(incomeContract, incomeContractMapper.selectById(incomeContractId))
                            .build(agreement.getCreateBy(), agreement.getCreateName()));
                }
                return result;
            }), McnErrorCode.FLOW_CALLBACK_HANDLE_EXCEPTION);
            //含有执行单才会发费用MQ
            if (AgreementChangeContentEnum.containsExcOrder(agreement.getChangeContent())) {
                incomeContractAgreementMessageProducer.sendRecordToMq(agreement.getId());
            }
        }
        approvalFlowService.sendNotify(approvalFlowDTO, incomeContract.getId(), incomeContract.getContractCode()
                , approvalEnum, status, agreement.getCreateBy(), agreement.getCreateName());
    }

    /**
     * 是否广告金额变更
     *
     * @return
     */
    @Deprecated
    private boolean isAdAmountChange(IncomeContract incomeContract, IncomeContractAgreement agreement) {
        //是否广告金额变更
        boolean adAmountChange = false;
        if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) && AgreementChangeContentEnum.containsAmount(agreement.getChangeContent())) {
            adAmountChange = ObjectUtil.defaultIfNull(incomeContract.getAdAmount(), BigDecimal.ZERO).compareTo(agreement.getAdAmount()) != 0;
        }
        return adAmountChange;
    }

    /**
     * 填充账号是否入驻
     *
     * @param excutionOrders
     */
    @Deprecated
    private void fillInSystemAdmin(List<ContractExcutionOrder> excutionOrders) {
        if (CollectionUtils.isEmpty(excutionOrders)) {
            return;
        }
        excutionOrders.forEach(e -> {
            e.setInSystemAdmin(starPlatformInfoService.getIsSystemAdmin(e.getStarPlatformInfoId(), e.getCooperationContent()));
        });
    }

    /**
     * 校验发票
     *
     * @param agreementAddDTO
     */
    @Deprecated
    private void verifyInvoice(IncomeAgreementAddDTO agreementAddDTO) {
        Integer invoiceForm = agreementAddDTO.getInvoiceForm();
        if (invoiceForm == null) {
            return;
        }
        InvoiceFormEnum invoiceFormEnum = InvoiceFormEnum.getByType(invoiceForm);
        if (agreementAddDTO.getCustomerBillingId() == null) {
            throw new BusinessException(McnErrorCode.NO_CUSTOMER_SIGN_SUBJECT);
        }
        switch (invoiceFormEnum) {
            case NEED_INVOICE:
                if (agreementAddDTO.getInvoiceType() == null) {
                    throw new BusinessException(McnErrorCode.NO_INVOICE_TYPE);
                }
                if (StrUtil.isBlank(agreementAddDTO.getInvoiceContent())) {
                    throw new BusinessException(McnErrorCode.NO_INVOICE_CONTENT);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 判断审批状态
     *
     * @param agreement {@link IncomeContractAgreement}
     * @param changeStatus                  {@link Integer}
     */
    private void verifyApprovalStatus(IncomeContractAgreement agreement, Integer changeStatus, IncomeContract incomeContract, Supplier<List<ContractExcutionOrder>> supplier) {
        BusinessAssert.isTrue(!ApprovalStatusEnum.isInvalid(agreement.getApprovalStatus()), McnErrorCode.AGREEMENT_INVALID);
        if (ApprovalStatusEnum.anyMatch(changeStatus, ApprovalStatusEnum.PASSED, ApprovalStatusEnum.REJECTED)) {
            BusinessAssert.isTrue(!ApprovalStatusEnum.isCancel(agreement.getApprovalStatus()),McnErrorCode.AGREEMENT_CANCELED);
        }
        if (ApprovalStatusEnum.isPassed(agreement.getApprovalStatus()) && ApprovalStatusEnum.isInvalid(changeStatus)) {
            throw new BusinessException(McnErrorCode.NON_VOIDABLE);
        }
        if (AgreementChangeContentEnum.containsExcOrder(agreement.getChangeContent()) && ApprovalStatusEnum.isInvalid(changeStatus)) {
            List<ContractExcutionOrder> executionOrderList = supplier.get();
            if (Objects.nonNull(executionOrderList)) {
                List<Integer> collect = executionOrderList.stream().map(ContractExcutionOrder::getApprovalStatus).distinct().collect(Collectors.toList());
                boolean allMatch = collect.stream().allMatch(x -> x.equals(ExcutionApprovalStatusEnum.INVALID.getCode()));
                BusinessAssert.isTrue(allMatch,McnErrorCode.SUPPLEMENTARY_AGREEMENT_RELATED_EXECUTION);
            }
        }
        if (ApprovalStatusEnum.isApproval(changeStatus)) {
            BusinessAssert.isFalse(AgreementChangeContentEnum.containsInvalid(agreement.getChangeContent()), "仅允许修改「我司合同主体、形式合同平台订单号」！");
            BusinessAssert.isTrue(incomeContactAgreementMapper.notExist(Wrappers.lambdaQuery(IncomeContractAgreement.class)
                .eq(IncomeContractAgreement::getIncomeContractId, incomeContract.getId())
                .ne(IncomeContractAgreement::getId, agreement.getId())
                .in(IncomeContractAgreement::getApprovalStatus, Arrays.asList(
                        ApprovalStatusEnum.UN_COMMIT.getCode(),
                        ApprovalStatusEnum.APPROVAL.getCode(),
                        ApprovalStatusEnum.REJECTED.getCode(),
                        ApprovalStatusEnum.CANCEL.getCode()))
                .eq(IncomeContractAgreement::getIsDelete, NumberCst.ZERO)
            ), "当前合同已存在进行中的补充协议，请勿重复添加！");
        }
        if (IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType())) {
            List<ContractExcutionOrder> platformReportIsFalseList = supplier.get().stream().filter(x -> !Integer.valueOf(9).equals(x.getApprovalStatus()) && Boolean.FALSE.equals(x.getPlatformReport())).collect(Collectors.toList());
            BusinessAssert.isTrue(CollectionUtils.isEmpty(platformReportIsFalseList), ParamErrorCst.FORM_CONTRACT_PLATFORM_REPORT_IS_TRUE);
        }
    }

    /**
     * 根据收入合同ID获取执行单
     * @param incomeContractId
     * @param agreementId
     * @return
     */
    private List<ContractExcutionOrder> getListByIncomeContractId(Long incomeContractId, Long agreementId) {
        return contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .eq(ContractExcutionOrder::getIncomeContractId, incomeContractId)
                .and(Objects.nonNull(agreementId), (wrapper) -> wrapper.ne(ContractExcutionOrder::getContractAgreementId, agreementId)
                        .or().isNull(ContractExcutionOrder::getContractAgreementId))
                .eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO)
                .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode()));
    }
}
